--
-- Author:      feilong
-- DateTime:    2020-02-27 10:59:15
-- Description: 1945游戏场景


	
-- require("boxclip.joystick")
-- require("boxclip.tools")
require("boxclip.console")
local MapIo = require("boxclip.MapIo")
local Sound = require("boxclip.Sound")
local Binds = require("boxclip.Binds")
-- require("boxclip.input")
require("boxclip.fonts")
require("boxclip.textures")
local Camera = require("boxclip.Camera")

	
local Physics = require("boxclip.Physics")
require("boxclip.collision")
local Weather = require("boxclip.Weather")
local Player = require("boxclip.Player")
local Popups = require("boxclip.Popups")
-- require("boxclip.menus")
-- require("boxclip.game")
-- require("boxclip.editor")
local EntityManger = require("boxclip.entities")
local ResLoader = require("boxclip.ResLoader")

--test parallax background layers
local test = love.graphics.newImage("res/images/test.png")
local test2 = love.graphics.newImage("res/images/test2.png")
test:setWrap("repeat", "clamp")
test2:setWrap("repeat", "clampzero")
local screen_w = love.graphics.getWidth()
local test_quad = love.graphics.newQuad( 0,0, screen_w,test:getHeight(), test:getDimensions() )
local test_quad2 = love.graphics.newQuad( 0,0, screen_w,test2:getHeight(), test2:getDimensions() )
local test_quad3 = love.graphics.newQuad( 0,0, screen_w,test:getHeight(), test:getDimensions() )


name = "Boxclip"
author = "ricky thomson"
version = "0.2.1"
build = "-alpha"
default_width = 400
default_height = 300

local Scene = require("ui.Scene")
local Game = class("Game", Scene)

function Game:ctor()
	self.super.ctor(self)

	world = self
	--背景
	self.img_bg1 = love.graphics.newImage("res/images/test.png")
	self.img_bg2 = love.graphics.newImage("res/images/test2.png")
	self.img_bg1:setWrap("repeat", "clamp")
	self.img_bg2:setWrap("repeat", "clampzero")
	self.quad_bg1 = love.graphics.newQuad( 0,0, screen_w,self.img_bg1:getHeight(), self.img_bg1:getDimensions() )
	self.quad_bg2 = love.graphics.newQuad( 0,0, screen_w,self.img_bg2:getHeight(), self.img_bg2:getDimensions() )
	self.quad_bg3 = love.graphics.newQuad( 0,0, screen_w,self.img_bg1:getHeight(), self.img_bg1:getDimensions() )


	self.map_name = "1_act1.lua"
	local res_loader = ResLoader.new() --资源列表
	global.res_loader = res_loader
	
	self.camera = nil
	local sound = Sound.new()
	global.sound = sound
	self.sound = global.sound

	self.player = Player.new()
	global.player = self.player

	self.mapio = MapIo.new()

	self.popups = Popups.new()
	global.popups = self.popups

	self.weather = Weather.new()
	global.weather = self.weather
	self.camera = Camera.new(0.8)
	global.camera = self.camera

	self.physics = Physics.new()
	global.physics = self.physics

	self.entity_manager = EntityManger.new()
	global.entity_manager = self.entity_manager

	self.binds = Binds.new()
	global.binds = self.binds
	console:init()
end

function Game:exit()

end


--设置主题
function Game:settheme(theme)
	--theme palettes for different level style
	--intialize default fallbacks
	-- love.filesystem.load( "boxclip/themes/default.lua" )( )
	-- theme = "swamp"
	--set the desired theme name
	world.theme = theme or "default"

	--load the theme file
	if love.filesystem.load( "boxclip/themes/".. theme ..".lua" )( ) then 
		console:print("failed to set theme:  " .. theme)
	else
	
		--background	
		love.graphics.setBackgroundColor(0.3,0.3,0.3,1)
		
		--only set background image if it exists
		if type(background) == "userdata" then
			background:setWrap("repeat", "repeat")
			background_quad = love.graphics.newQuad( 0,0, self.screen_w,self.screen_h, background:getDimensions() )
		end
	
		console:print("set theme: " .. theme)
		
	end
	
end
--开局时的标题封面
-- function Game:initsplash()
-- 	--loading/act overlay
-- 	world.splash = {}
-- 	world.splash.bg = love.graphics.newImage("data/images/platforms/0001.png")
-- 	world.splash.bg:setWrap("repeat", "repeat")
-- 	world.splash.active = true
-- 	world.splash.opacity = 1
-- 	world.splash.timer = 3
-- 	world.splash.fadespeed = 1
-- 	world.splash.box_h = 100
-- 	world.splash.box_y = -world.splash.box_h/2
-- 	world.splash.text_y = -world.splash.box_h/2
-- 	-- transitions:fadein()
-- end

--默认配置
function Game:setdefaults()
	--defaults in case not specified in map file
	
	--default gravity
	world.gravity = 2000

	--default scores (used to track/reset on death)
	-- for remembering player.score and player.gems
	world.score = 0
	world.gems = 0
	
	--reset time
	world.time = 0
	
	world.complete = false
	
	--default deadzone
	-- anything falling past this point will land here
	-- (used to stop entities being lost, eg; falling forever)
	-- if it collides with gameworld, increase this value so it's below the furthest entity
	-- world.deadzone = 2000 
	
	--default theme/pallete
	self:settheme("default")
	
	--default sound options
	world.mapmusic = 0
	world.mapambient = 0
	
	--default map title
	world.maptitle = "unnamed map"
	
	--default map to load on finish
	--either mapname.lua or title
	world.nextmap = "title"
end


function Game:init(gamemode) 
	mode = gamemode or "game"
	--console = false
	editing = false
	self.paused = false
	
	-- world loading/splash/act display
	-- if mode == "game" then
	-- 	self:initsplash()
	-- else
	-- 	world.splash.active = false
	-- end
	
	--collision counter (console/debug)
	world.collision = 0
	
	self.screen_w = love.graphics.getWidth()
	self.screen_h = love.graphics.getHeight()

	self:reset()
	self:setdefaults()
	self.mapio:loadmap(self.map_name)

	self:settheme("frost")
	-- find the spawn entity
	-- set as player spawn position
	for _, portal in ipairs(world.entities.portal) do
		if portal.type == "spawn" then
			self.player.spawnX = portal.x
			self.player.spawnY = portal.y
		end
	end	
	
	self:resetcamera()
	self:savestate()

	local cheats = {
		catlife = false, --盾
		jetpack = false, --喷气
		magnet = false, --磁铁
		millionare = false,
	}
	--enable cheats, if any
	if cheats.catlife then 
		self.player.lives = self.player.lives +  9 
	end
	if cheats.millionare then 
		self.player.score = self.player.score +  "1000000" 
	end
	
	self.player:respawn() --复活
	self.sound:playbgm() --播放背景音乐

	console:print("initialized world")
end


--视觉差
function Game:drawparallax()

	--TODO this still needs fixing
	
	if editing then return end
	love.graphics.setColor(1,1,1,1)

	
	--paralax background sky
	if type(background) == "userdata" then
		love.graphics.draw(
			background, background_quad,0,0
		)
	end

	--back layer
	love.graphics.setColor(
		platform_top_r/2,
		platform_top_g/2,
		platform_top_b/2,
		1
	)
	self.quad_bg1:setViewport(
		(self.camera.x*2)/10*self.camera.scale,((self.camera.y*2)/40),self.screen_w,self.screen_h
	)
	love.graphics.draw(
		self.img_bg1,
		self.quad_bg1,				
		0,0
	)
	--中景
	love.graphics.setColor(
		platform_behind_r,
		platform_behind_g,
		platform_behind_b,
		1
	)
	self.quad_bg2:setViewport((self.camera.x*3)/10*self.camera.scale,((self.camera.y*3)/35),self.screen_w,self.screen_h)
	love.graphics.draw(
		self.img_bg1,
		self.quad_bg2,				
		0,0
	)
	
	--前景
	love.graphics.setColor(
		platform_top_r/1.5,
		platform_top_g/1.5,
		platform_top_b/1.5,
		1
	)
	self.quad_bg3:setViewport(
		(self.camera.x*4)/10*self.camera.scale,((self.camera.y*4)/30),self.screen_w,self.screen_h
	)
	love.graphics.draw(
		self.img_bg1,
		self.quad_bg3,				
		0,0
	)
	--]]
	

end

-- function Game:drawsplash()
-- 	if debug then return end
-- 	-- textured background
-- 		love.graphics.setColor(0.2,0.2,0.2,world.splash.opacity)		
-- 		self.splash.quad = love.graphics.newQuad( 0,0, self.screen_w,self.screen_h, self.splash.bg:getDimensions() )
-- 		love.graphics.draw(self.splash.bg, self.splash.quad, 0, 0)
	
-- 		--box
-- 		love.graphics.setColor(platform_r/2,platform_g/2,platform_b/2,world.splash.opacity)
-- 		love.graphics.rectangle("fill", 0,world.splash.box_y+self.screen_h/2,self.screen_w, world.splash.box_h )
		
-- 		--text
-- 		love.graphics.setFont(fonts.huge)
-- 		love.graphics.setColor(1,1,1,world.splash.opacity)
-- 		love.graphics.print(world.maptitle, self.screen_w-fonts.huge:getWidth(world.maptitle)-100, world.splash.text_y+self.screen_h/2+world.splash.box_h/2)
-- 		love.graphics.setFont(fonts.default)
-- end

function Game:draw()
	

	self:drawparallax()
	
	--固定
	self.camera:attach()
	
	--[[ draw deadzone here
		unimplemented
	--]]

	love.graphics.setColor(1,1,1,1)

	-- decals:draw()
	-- props:draw()
	
	-- platforms:draw()
	-- springs:draw()
	-- bumpers:draw()
	-- checkpoints:draw()
	-- crates:draw()
	-- portals:draw()
	-- coins:draw()
	-- pickups:draw()
	-- enemies:draw()
	-- traps:draw()
	-- materials:draw()
	-- tips:draw()
	self.entity_manager:draw()

	self.player:draw()	
	self.weather:draw()
	self.popups:draw()

	--分离
	self.camera:detach()
	console:draw()
	
	if mode == "editing" then
		editor:draw()
	end
	
	self.camera:draw()	
	--draw the hud/scoreboard
	-- if mode =="game" then
		
	-- 	-- self:drawhud()
		
	-- 	-- if world.splash.opacity > 0 then 
	-- 	-- 	self:drawsplash()
	-- 	-- end
	-- end
	
	
	-- if world.complete then
	-- 	-- self:drawscoreboard()
	-- end
	
	-- if paused then
	-- 	love.graphics.setColor(0,0,0,0.6)
	-- 	love.graphics.rectangle("fill",0,0,self.screen_w,self.screen_h)
	-- 	love.graphics.setColor(1,1,1,0.6)
	-- 	love.graphics.setFont(fonts.huge)
	-- 	love.graphics.printf("PAUSED", 0,self.screen_h/3,self.screen_w,"center",0,1,1)
	-- 	love.graphics.setFont(fonts.default)
	-- 	love.graphics.line(self.screen_w/2.5,self.screen_h/3,self.screen_w-self.screen_w/2.5,self.screen_h/3)
	-- 	love.graphics.line(self.screen_w/2.5,self.screen_h/3+40,self.screen_w-self.screen_w/2.5,self.screen_h/3+40)
	-- end
	

end

	
function Game:reset()
	--clear all entities from the world
	--reinitialise default tables

	world.entities = {
		--maybe these should be swapped around
		--then use group name for entity info (editor)
		["material"] = {group = "materials"},
		["trap"] = {group = "traps"},
		["enemy"] = {group = "enemies"},
		["pickup"] = {group = "pickups"},
		["coin"] = {group = "coins"},
		["portal"] = {group = "portals"},
		["crate"] = {group = "crates"},
		["checkpoint"] = {group = "checkpoints"},
		["bumper"] = {group = "bumpers"},
		["spring"] = {group = "springs"},
		["platform"] = {group = "platform"},
		["prop"] = {group = "props"},
		["decal"] = {group = "decals"},
		["tip"] = {group = "tips"}

	}
end


--是否要在窗口中显示物体
function Game:inview(entity) 
	local x,y = self.camera:toWorldCoords(entity.x,entity.y)
	
	if entity.swing then
		if (self.camera.x + self.screen_w/2/self.camera.scale > entity.xorigin-entity.radius) 
		and (self.camera.x - self.screen_w/2/self.camera.scale < entity.xorigin+entity.w+entity.radius)
		and (self.camera.y + self.screen_h/2/self.camera.scale > entity.yorigin-entity.radius)
		and (self.camera.y - self.screen_h/2/self.camera.scale < entity.yorigin+entity.h+entity.radius)
			then
			world.collision = world.collision +1
			return true
		end
	else
		--decides if the entity is visible to the camera
		if (self.camera.x + (self.screen_w/2/self.camera.scale) > entity.x ) 
		and (self.camera.x - (self.screen_w/2/self.camera.scale) < entity.x+entity.w)
		and (self.camera.y + (self.screen_h/2/self.camera.scale) > entity.y)
		and (self.camera.y - (self.screen_h/2/self.camera.scale) < entity.y+entity.h)
			then
			world.collision = world.collision +1
			return true
		end
	end
end


function Game:update(dt)

	if not self.paused then 
		self.camera:update(dt)
		self.weather:update(dt)
		self.physics:update(dt)
		self.popups:update(dt)
		self.player:update(dt)
		-- platforms:update(dt)
		-- decals:update(dt)
		-- materials:update(dt)
		-- portals:update(dt)
		-- checkpoints:update(dt)
		-- springs:update(dt)
		-- coins:update(dt)
		-- pickups:update(dt)
		-- bumpers:update(dt)
		-- enemies:update(dt)
		-- tips:update(dt)
		-- console:update(dt)
		self.entity_manager:update(dt)

		world.collision = 0

		-- camera follows player
		if self.player.alive and not world.complete then
			self.camera:follow(self.player.x+self.player.w/2, self.player.y+self.player.h/2)
		end

		-- draw background
		if type(background) == "userdata" then
			background_scroll = background_scroll + background_scrollspeed * dt
			if background_scroll > background:getWidth()then
				background_scroll = background_scroll - background:getWidth()
			end
			background_quad:setViewport(self.camera.x/50-background_scroll,-self.camera.y/100,self.screen_w,self.screen_h )
		else
			background_scroll = 0
		end

		for _,p in ipairs(world.entities.portal) do
			if p.type == "goal" and p.activated then
				-- self:endoflevel()
			end
		end

	
	end
end

--重新设置相机位置
function Game:resetcamera()

	self.camera:setFollowStyle('LOCKON')
	self.camera:setFollowLerp(0.065)
	--camera:setFollowLerp(0.2)
end


function Game:savestate()
	world.score = self.player.score
	world.gems = self.player.gems
	world.state = table.deepcopy(world.entities)
end
function Game:loadstate()
	self.player.score = world.score
	self.player.gems = world.gems
	--恢复场景
	world.entities = table.deepcopy(world.state)
end



--按键控制
function Game:keypressed(key)

	--debug mode console
	if console.active then
		console:keypressed(key)
		return
	else
		if key == self.binds.console then
			console:toggle()
		end
	end
	
	if     mode == "title" then title:keypressed(key)
	elseif mode == "editing" then editor:keypressed(key)
	elseif mode == "gameover" then gameover:keypressed(key)
	elseif mode == "game" then

		if key == self.binds.pause then
			if self.paused then
			 	self.sound:playbgm()
			else 
				self.sound:pausebgm()
			end
			self.paused = not self.paused
			self.sound:playEffect("beep")
		end
	end

	--quit
	if mode == "game" or mode == "editing" then
		self.player:keypressed(key) 
		
		if key == self.binds.exit then
			love.audio.stop()
			title:init()
		end
	end

	--[[ take a screenshot and save to local game data folder
		   * Linux/*nix = ~/.local/share/love/boxclip/screenshots/
		   * Windows    = ????
	--]]
	if key == self.binds.screenshot then
		local file = "screenshots/" .. os.date("%Y-%m-%d_%H%M%S") .. ".png"
		love.graphics.captureScreenshot(file)
		console:print("screenshot: " .. self.mapio.path .. "/" .. file .. " saved")
	end

	--toggle fullscreen
	if key == self.binds.fullscreen then 
		local fs, fstype = love.window.getFullscreen()
		if fs then
			local success = love.window.setMode( default_width,default_height, {resizable=true, vsync=false, minwidth=default_width, minheight=default_height})
			if mode == "game" or mode =="editing" then
				self:resetcamera()
			end
		else
			local success = love.window.setFullscreen( true, "desktop" )
		end
		-- if not success then
		-- 	console:print("Failed to toggle fullscreen mode!")
		-- end
	 end
		
	--toggle sound
	if key == self.binds.mute then 
		self.sound:toggle()
	end

	--[[ open local data folder with user set application
	     NOTE to change this:
	     $ xdg-mime default Thunar.desktop inode/directory
	--]]
	if key == self.binds.savefolder then
		love.system.openURL( "file://"..self.mapio.path )
	end

end


function Game:textinput(t)
	console:textinput(t)
end


return Game